home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 02 - 1986 / 02.10 Oct 86.sit / 02.10 Oct 86 / trap sources / trapspeed.pas / trapspeed.pas
Encoding:
Pascal/Delphi Source File  |  1986-09-05  |  6.3 KB  |  146 lines  |  [TEXT/EDIT]

  1. { traptime -- A program to time various methods of doing a toolbox trap:
  2.   The usual method, calling a user-written routine to do the work, doing the
  3.   work in-line, and calling the ROM routine directly without going through
  4.   the trap dispatcher.  Times for all routines are written on the screen in
  5.   ticks for a given number of calls, then the number of calls is varied for
  6.   improved accuracy.
  7.  
  8.   Mike Morton, November 1985. Modified for TML Pascal, June 1986. }
  9.  
  10. program traptime (output);        { "(output)" lets us do writelns }
  11.  
  12. {$I MemTypes.ipas  }
  13. {$I QuickDraw.ipas }            { we use Quickdraw graphics }
  14. {$I OSIntf.ipas }            { and OS definitions }
  15. {$I ToolIntf.ipas }            { and Toolbox calls }
  16.  
  17. var                        { program-wide variables }
  18.   basetime: longint;                { constant overhead for the loop }
  19.   loops: longint;                { number of iterations to time }
  20.   start: longint;                { starting tickcount for timing }
  21.   Event:EventRecord;
  22.   DoIt: Boolean;
  23.   Finished:Boolean;
  24.  
  25. { getbasetime -- Find the time for the loop when nothing is done inside it.
  26.   This tells us the overhead which should be subtracted from other timings. }
  27. function getbasetime: longint;
  28. var count: longint;                { loop counter }
  29. begin;
  30.   start := tickcount;                { snapshot starting time }
  31.   for count := 1 to loops do            { loop a bunch of times... }
  32.     ;                        { ...doing nothing each time }
  33.   getbasetime := tickcount-start;       { calculate elapsed time }
  34. end;                        { function "getbasetime" }
  35.  
  36. { usualtime -- Find the time used to call the ROM the usual way.  This, and
  37.   all timing routines, should look as much as possible like "getbasetime". }
  38. function usualtime: longint;
  39. var
  40.   count: longint;                { loop counter }
  41.   pt: point;                    { point to assign to }
  42.   x, y: integer;                { coordinates to assign to the point }
  43. begin;
  44.   start := tickcount;                { snapshot starting time }
  45.   for count := 1 to loops do            { this time, inside the loop... }
  46.     setpt (pt, x, y);                { ...we do the ROM call }
  47.   usualtime := tickcount-start;            { calculate elapsed time }
  48. end;                        { function "usualtime" }
  49.  
  50.  
  51. { setmypt -- This isn't a timing function like the others; it's a replacement
  52.   for the ROM's "setpt" routine, to see how fast we can do it ourselves. }
  53. procedure setmypt (VAR pt: point; x, y: integer);
  54. begin;
  55.   pt.h := x; pt.v := y;                { assign to the coordinates; easy! }
  56. end;                        { procedure "setmypt" }
  57.  
  58. { myowntime -- Time the assignment using our own procedure. }
  59. function myowntime: longint;
  60. var
  61.   count: longint;                { loop counter }
  62.   pt: point;                    { point to assign to }
  63.   x, y: integer;                { coordinates to assign to point }
  64. begin;
  65.   start := tickcount;                { snapshot starting time }
  66.   for count := 1 to loops do            { this time, inside the loop... }
  67.     setmypt (pt, x, y);                { ...we call our own routine }
  68.   myowntime := tickcount-start;            { calculate elapsed time }
  69. end;                        { function myowntime }
  70.  
  71. { inlintime -- The most straightforward way: we do the assignment in the loop. }
  72. function inlintime: longint;
  73. var
  74.   count: longint;                { loop counter }
  75.   pt: point;                    { point to assign to }
  76.   x, y: integer;                { coordinates to assign to point }
  77. begin;
  78.   start := tickcount;                { snapshot starting time }
  79.   for count := 1 to loops do            { this time, inside the loop... }
  80.     begin; pt.h := x; pt.v := y; end;   { ...we do the assignment right here }
  81.   inlintime := tickcount-start;            { calculate elapsed time }
  82. end;                        { function inlintime }
  83.  
  84. { setptx -- This is another replacement for "setpt".  It takes an extra
  85.   parameter, the previously determined address of "setpt", and calls that
  86.   address, leaving the other parameters for "setpt".  Unfortunately, TML
  87.   Pascal doesn't mimic Lisa Pascal closely enough to allow us to generate
  88.   more than one word of code in a single declaration.  So we have two
  89.   procedures -- these MUST always be used together!  TML says their 2.0
  90.   release of the compiler will be Lisa-compatible on this score, so this
  91.   unsightly workaround won't be needed any more. }
  92. procedure setptx1 (var pt: point; h, v: integer; addr: longint);
  93.       INLINE   $205F;     { MOVE.L (A7)+,A0  ; pop routine's address into A0… }
  94. procedure setptx2;
  95.       INLINE   $4E90;     { JSR      (A0)        ; …and call that address   }
  96.  
  97. { gettrtime -- The last and most complicated way of calling the routine.  We
  98.   use the trap address to call it directly. }
  99. function gettrtime: longint;
  100. var
  101.   addr: longint;                { actual address of "setpt" }
  102.   count: longint;                { loop counter }
  103.   pt: point;                    { point to assign to }
  104.   x, y: integer;                { coordinates to assign to point }
  105. begin;
  106.   addr := gettrapaddress ($a880);       { find where the routine lives }
  107.   start := tickcount;                { snapshot starting time }
  108.   for count := 1 to loops do begin    { this time, inside the loop... }
  109.     setptx1 (pt, x, y, addr);            { ...we call on ROM, but differently }
  110.     setptx2;                { (kludge to sneak in 2nd instruction }
  111.   end;
  112.   gettrtime := tickcount-start;            { calculate elapsed time }
  113. end;                        { function gettrtime }
  114.  
  115. begin;                        { *** main program *** }
  116.   writeln ('If launching from a floppy, wait for it to stop and click to begin...');
  117.   while not button do; while button do; { cheap way to wait for a click }
  118.  
  119.   loops := 10000;                { start with a small loop size... }
  120.   while loops <= 100000 do            { ...and go through several loop sizes }
  121.   begin;
  122.     basetime := getbasetime;            { find constant overhead for the loop }
  123.  
  124.     writeln ('number of loops:', loops, '; base time is:', basetime);
  125.     writeln ('time for usual method is..........: ', usualtime - basetime);
  126.     writeln ('time for calling my own routine is: ', myowntime - basetime);
  127.     writeln ('time for doing it in-line is......: ', inlintime - basetime);
  128.     writeln ('time for doing it with gettrapaddr: ', gettrtime - basetime);
  129.     writeln;
  130.  
  131.     loops := loops * 10;            { loop sizes increase exponentially }
  132.   end;
  133.  
  134.   flushevents(EveryEvent,0);
  135.    writeln ('click to exit or take snapshot…');            { don't go away yet... }
  136.   Repeat
  137.   systemtask;
  138.  DoIt:=GetNextEvent(EveryEvent,Event);
  139.  if DoIt then
  140.      Case Event.what of
  141.          KeyDown: begin end;
  142.          Mousedown: begin Finished:=true; end;
  143.      End;
  144. Until Finished;
  145. end.                        { of main program "traptime"  }
  146.